// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2023, Phytium Technology Co., Ltd.
 * This file describes the power management based
 * on cpld on Phytium pe2201 board.
 */

#include <common.h>
#include <asm/io.h>
#include <e_uart.h>
#include "power_manage.h"
#include "../parameter/parameter.h"
#include "../cpu.h"

/*
 * use gpio send commands to the cpld to manage the power supply
 */
void send_cpld_ctr(uint32_t cmd)
{
	p_printf("u-boot : send cmd to cpld : %d\n", cmd);
	int ret, cfg;
	u32 port_level = 0;
	int port = 0;

	/* gpio pad */
	ret = readl((size_t)(PAD_BASE + DS_AG55));	//gpio1_0:func5
	//int pad_recv0 = ret;
	ret |= (1 << 0);
	ret &= ~(1 << 1);
	ret |= (1 << 2);
	writel(ret, (size_t)(PAD_BASE + DS_AG53));

	ret = readl((size_t)(PAD_BASE + DS_AG53));	//gpio1_1:func5
	//int pad_recv1 = ret;
	ret |= (1 << 0);
	ret &= ~(1 << 1);
	ret |= (1 << 2);
	writel(ret, (size_t)(PAD_BASE + DS_AG53));

	/* send cpld */
	/* configure GPIO_SWPORTA_DDR before reading*/
	cfg = readl((u64)(GPIO1_BASE + GPIO_SWPORTA_DDR));
	//int cfg_recv = ret;
	cfg |= (1 << port);
	port = 1;
	cfg |= (1 << port);
	/* configure output mode，0：input， 1：output */
	writel(cfg, (u64)(GPIO1_BASE + GPIO_SWPORTA_DDR));

	/* transmit level value */
	port_level = readl((u64)(GPIO1_BASE + GPIO_SWPORTA_DR));
	port = 0;
	port_level |= (1 << port);
	writel(port_level, (u64)(GPIO1_BASE + GPIO_SWPORTA_DR));	//start
	mdelay(2);

	port = 1;
	port_level |= (1 << port);
	int high = port_level;

	port_level &= ~(1 << port);
	int low = port_level;

	for (int i = 0; i < cmd; i++) {
		writel(high, (u64)(GPIO1_BASE + GPIO_SWPORTA_DR));
		mdelay(1);
		writel(low, (u64)(GPIO1_BASE + GPIO_SWPORTA_DR));
		mdelay(1);
	}
	mdelay(2);
	port = 0;
	port_level &= ~(1 << port);
	writel(port_level, (u64)(GPIO1_BASE + GPIO_SWPORTA_DR));	//end

	/* recover */
	//writel(cfg_recv, (size_t)(GPIO1_BASE + GPIO_SWPORTA_DDR));
	//writel(pad_recv0, (size_t)(PAD_BASE + DS_AG55));			//gpio1_0:func5
	//writel(pad_recv1, (size_t)(PAD_BASE + DS_AG53));			//gpio1_1:func5
}

int gpio_get_s3_flag(void)
{
	int ret, cfg;
	int port = 0;

	/* gpio pad */
	ret = readl((size_t)(PAD_BASE + DS_AE55));	//gpio1_2:func5
	//int pad_recv0 = ret;
	ret |= (1 << 0);
	ret &= ~(1 << 1);
	ret |= (1 << 2);
	writel(ret, (size_t)(PAD_BASE + DS_AE55));
	mdelay(10);

	/* configure GPIO_SWPORTA_DDR before reading */
	cfg = readl((size_t)(GPIO1_BASE + GPIO_SWPORTA_DDR));
	//int cfg_recv = cfg;
	/* configure output mode，0：input， 1：output */
	port = 2;
	cfg &= ~(1 << port);
	writel(cfg, (size_t)(GPIO1_BASE + GPIO_SWPORTA_DDR));

	/* read GPIO_SWPORTA_DDR value */
	ret = readl((size_t)(GPIO1_BASE + GPIO_EXT_PORTA));
	debug("s3 flag ret = 0x%x\n", ret);

	/* recover */
	///writel(cfg_recv, (size_t)(GPIO1_BASE + GPIO_SWPORTA_DDR));
	//writel(pad_recv0, (size_t)(PAD_BASE + DS_AE55));

	/* Check whether the corresponding io pin is high */
	if (ret & 0x4)
		return 1;
	else
		return 0;
}
